package com.yfp.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.Client;
import com.yfp.client.domain.ClientHistoryInfo;
import com.yfp.client.domain.vo.ClientHealthGuidePageVO;
import com.yfp.client.domain.vo.ClientHealthLogStatisticVO;
import com.yfp.client.domain.vo.ClientHistoryInfoBodyVO;
import com.yfp.client.domain.vo.ClientHistoryInfoVO;
import com.yfp.client.mapper.ClientHistoryInfoMapper;
import com.yfp.client.service.ClientHealthLogService;
import com.yfp.client.service.ClientHistoryInfoService;
import com.yfp.client.service.ClientService;
import com.yfp.client.util.SecurityUtils;
import com.yfp.common.core.utils.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 *
 * @description 针对表【client_history_info(客户历史信息表)】的数据库操作Service实现
 * @createDate 2025-02-12 10:04:35
 */
@Service
public class ClientHistoryInfoServiceImpl extends ServiceImpl<ClientHistoryInfoMapper, ClientHistoryInfo> implements ClientHistoryInfoService {

    @Resource
    private ClientService clientService;
    @Resource
    private ClientHealthLogService clientHealthLogService;
    @Resource
    private ClientHistoryInfoMapper clientHistoryInfoMapper;

    @Override
    public List<ClientHistoryInfoVO> getClientHistoryInfoList() {
        String clientId = SecurityUtils.getClientId();

        List<ClientHistoryInfo> clientHistoryInfos = clientHistoryInfoMapper.selectByClientId(clientId);

        List<ClientHistoryInfoVO> clientHistoryInfoBodyVOS = BeanUtil.copyToList(clientHistoryInfos, ClientHistoryInfoVO.class);

        // 按时间排序，比较相邻两条记录weight的差值
        List<ClientHistoryInfoVO> sortedList = clientHistoryInfoBodyVOS.stream().sorted(Comparator.comparing(ClientHistoryInfoVO::getCreateTime)).toList();
        for (int i = 0; i < sortedList.size() - 1; i++) {
            ClientHistoryInfoVO current = sortedList.get(i);
            ClientHistoryInfoVO next = sortedList.get(i + 1);

            BigDecimal weightDifference = NumberUtil.sub(next.getWeight(), current.getWeight());
            next.setDiff(weightDifference);
        }
        clientHistoryInfoBodyVOS = clientHistoryInfoBodyVOS.stream().filter(item -> !NumberUtil.equals(item.getDiff(), BigDecimal.ZERO)).sorted(Comparator.comparing(ClientHistoryInfoVO::getCreateTime, Comparator.reverseOrder())).toList();
        return clientHistoryInfoBodyVOS;
    }

    @Override
    public ClientHistoryInfoBodyVO getClientHistoryInfo() {

        String clientId = SecurityUtils.getClientId();

        List<ClientHistoryInfo> clientHistoryInfos = clientHistoryInfoMapper.selectByClientId(clientId);
        List<ClientHistoryInfoVO> clientHistoryInfoBodyVOS = BeanUtil.copyToList(clientHistoryInfos, ClientHistoryInfoVO.class);

        // 按时间排序，找到与第一条weight不同的数据
        List<ClientHistoryInfoVO> clientHistoryInfoList = clientHistoryInfoBodyVOS.stream().sorted(Comparator.comparing(ClientHistoryInfoVO::getCreateTime, Comparator.reverseOrder())).toList();
        ClientHistoryInfoVO first = CollUtil.get(clientHistoryInfoList, 0);
        List<ClientHistoryInfoVO> clientHistoryInfoList2 = clientHistoryInfoList.stream().filter(item -> !NumberUtil.equals(item.getWeight(), first.getWeight())).sorted(Comparator.comparing(ClientHistoryInfoVO::getCreateTime, Comparator.reverseOrder())).toList();
        ClientHistoryInfoVO last = CollUtil.get(clientHistoryInfoList2, 0);

        ClientHistoryInfoBodyVO clientHistoryInfoBodyVO = new ClientHistoryInfoBodyVO();
        clientHistoryInfoBodyVO.setWeight(first.getWeight());
        clientHistoryInfoBodyVO.setHeight(first.getHeight());
        clientHistoryInfoBodyVO.setBmi(this.calculateBMI(first.getHeight(), first.getWeight()));

        if (Objects.nonNull(last)) {
            clientHistoryInfoBodyVO.setDiff(NumberUtil.sub(first.getWeight(), last.getWeight()));
        }

        return clientHistoryInfoBodyVO;
    }

    @Override
    public BigDecimal calculateBMI(BigDecimal height_CM, BigDecimal weight) {
        //  BMI = 体重（公斤）/身高（米）²

        BigDecimal height_M = NumberUtil.div(height_CM, NumberUtil.toBigDecimal("100"));

        BigDecimal mul = NumberUtil.mul(height_M, height_M);
        BigDecimal bigDecimal = NumberUtil.div(weight, mul).setScale(2, RoundingMode.HALF_UP);
        return bigDecimal;
    }

    @Override
    public void saveClientHistoryInfo(Client client) {
        ClientHistoryInfo clientHistoryInfo = new ClientHistoryInfo();
        clientHistoryInfo.setClientId(client.getId());
        clientHistoryInfo.setWeight(BigDecimal.valueOf(client.getWeight()));
        clientHistoryInfo.setCreateTime(DateUtil.date());
        clientHistoryInfo.setHeight(BigDecimal.valueOf(client.getHeight()));
        clientHistoryInfo.setSex(client.getSex());
        clientHistoryInfo.setBirthday(client.getBirthday());
        clientHistoryInfoMapper.insert(clientHistoryInfo);
    }

    @Override
    public ClientHistoryInfo lastClientHealthLog(String clientId, Date endTime) {
        return clientHistoryInfoMapper.lastClientHealthLog(clientId, endTime);
    }

    @Override
    public void saveClientHistoryInfoCompareOld(Client clientNew) {
        try {
            Client clientOld = clientService.getById(clientNew.getId());

            Client client = new Client();
            client.setSex(clientOld.getSex());
            client.setBirthday(clientOld.getBirthday());
            client.setWeight(clientOld.getWeight());
            client.setHeight(clientOld.getHeight());

            if (StringUtils.isNotEmpty(clientNew.getSex()) && !StringUtils.equals(clientNew.getSex(), clientOld.getSex())) {
                client.setId(clientNew.getId());
                client.setSex(clientNew.getSex());
            }
            if (StringUtils.isNotEmpty(clientNew.getBirthday()) && !StringUtils.equals(clientNew.getBirthday(), clientOld.getBirthday())) {
                client.setId(clientNew.getId());
                client.setBirthday(clientNew.getBirthday());
            }
            if (Objects.nonNull(clientNew.getWeight()) && !NumberUtil.equals(NumberUtil.toBigDecimal(clientNew.getWeight()), NumberUtil.toBigDecimal(clientOld.getWeight()))) {
                client.setId(clientNew.getId());
                client.setWeight(clientNew.getWeight());
            }
            if (Objects.nonNull(clientNew.getHeight()) && !NumberUtil.equals(NumberUtil.toBigDecimal(clientNew.getHeight()), NumberUtil.toBigDecimal(clientOld.getHeight()))) {
                client.setId(clientNew.getId());
                client.setHeight(clientNew.getHeight());
            }

            if (Objects.nonNull(client.getId())) {
                this.saveClientHistoryInfo(client);
            }
        } catch (Exception e) {
            log.error("saveClientHistoryInfoCompareOld error:{}", e);
        }

    }

    @Override
    public ClientHistoryInfo firstClientHealthLog(String clientId, Date startTime) {
        return clientHistoryInfoMapper.firstClientHealthLog(clientId, startTime);
    }

    @Override
    public ClientHealthGuidePageVO guidePage() {
        String clientId = SecurityUtils.getClientId();
        Client client = clientService.getById(clientId);

        ClientHealthGuidePageVO clientHealthGuidePageVO = new ClientHealthGuidePageVO();
        clientHealthGuidePageVO.setBmi(this.calculateBMI(NumberUtil.toBigDecimal(client.getHeight()), NumberUtil.toBigDecimal(client.getWeight())));
        // 建议体重范围
        // 最小体重18.5*（身高米）²，最大体重23.9*（身高米）²
        BigDecimal height_M = NumberUtil.div(client.getHeight(), NumberUtil.toBigDecimal("100"));
        clientHealthGuidePageVO.setWeightLow(NumberUtil.mul(NumberUtil.toBigDecimal("18.5"), height_M, height_M));
        clientHealthGuidePageVO.setWeightHigh(NumberUtil.mul(NumberUtil.toBigDecimal("23.9"), height_M, height_M));
        // 热量缺口
        DateTime date = DateUtil.date();
        ClientHealthLogStatisticVO clientHealthLogStatistic = clientHealthLogService.getClientHealthLogStatistic(DateUtil.beginOfDay(date), DateUtil.endOfDay(date));
        clientHealthGuidePageVO.setGapKcal(clientHealthLogStatistic.getGapKcal());

        return clientHealthGuidePageVO;
    }
}




